﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using Autodesk.Revit.DB;
using YJKRGeometry;
using Teigha.Core;
using Teigha.TD;

namespace QuickModel.InteractiveOperation
{
	public class DwgManager
	{
		public DwgManager(string strDwgFilePath)
		{
			this.m_systemServices = new ExSystemServices();
			TD_Db.odInitialize(this.m_systemServices);
			this.m_hostAppServices = new ExHostAppServices();
			this.m_db = this.m_hostAppServices.readFile(strDwgFilePath);
			this.m_db.setCurrentUCS(OrthographicView.kTopView);
		}

		public bool TryGetTextByLayer(string strLayerName, ref List<DwgTextInfo> lstDwgTextInfo)
		{
			try
			{
				List<OdDbEntity> list = new List<OdDbEntity>();
				bool flag = !this.TryGetEntitiesByLayer(strLayerName, EntityType.eText, ref list);
				if (flag)
				{
					return false;
				}
				List<OdDbText> list2 = list.ConvertAll<OdDbText>((OdDbEntity entity) => entity as OdDbText);
				foreach (OdDbText odDbText in list2)
				{
					bool flag2 = odDbText == null;
					if (!flag2)
					{
						DwgTextInfo item = new DwgTextInfo(odDbText, OdGeMatrix3d.kIdentity);
						lstDwgTextInfo.Add(item);
					}
				}
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		public bool TryGetMTextByLayer(string strLayerName, ref List<DwgTextInfo> lstDwgTextInfo)
		{
			try
			{
				List<OdDbEntity> list = new List<OdDbEntity>();
				bool flag = !this.TryGetEntitiesByLayer(strLayerName, EntityType.eMText, ref list);
				if (flag)
				{
					return false;
				}
				List<OdDbMText> list2 = list.ConvertAll<OdDbMText>((OdDbEntity entity) => entity as OdDbMText);
				foreach (OdDbMText odDbMText in list2)
				{
					bool flag2 = odDbMText == null;
					if (!flag2)
					{
						DwgTextInfo item = new DwgTextInfo(odDbMText, OdGeMatrix3d.kIdentity);
						lstDwgTextInfo.Add(item);
					}
				}
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		public bool TryGetAttribueTextByLayer(string strLayerName, ref List<DwgTextInfo> lstDwgTextInfo)
		{
			try
			{
				List<OdDbEntity> list = new List<OdDbEntity>();
				List<OdDbBlockReference> list2 = new List<OdDbBlockReference>();
				bool flag = !this.TryGetEntitiesByType(ref list, EntityType.eBlockRef, "");
				if (flag)
				{
					return false;
				}
				list2.AddRange(list.ConvertAll<OdDbBlockReference>((OdDbEntity entity) => entity as OdDbBlockReference));
				foreach (OdDbBlockReference odDbBlockReference in list2)
				{
					OdDbObjectIterator odDbObjectIterator = odDbBlockReference.attributeIterator();
					odDbObjectIterator.start();
					while (!odDbObjectIterator.done())
					{
						OdDbEntity odDbEntity = odDbObjectIterator.entity(OpenMode.kForWrite, false);
						bool flag2 = odDbEntity == null;
						if (!flag2)
						{
							bool flag3 = odDbEntity is OdDbAttribute;
							if (flag3)
							{
								OdDbAttribute odDbAttribute = odDbEntity as OdDbAttribute;
								bool flag4 = odDbAttribute.layer() == strLayerName && !odDbAttribute.isInvisible();
								if (flag4)
								{
									DwgTextInfo item = new DwgTextInfo(odDbAttribute, OdGeMatrix3d.kIdentity);
									lstDwgTextInfo.Add(item);
								}
							}
						}
						odDbObjectIterator.step();
					}
				}
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		public bool TryGetLinesByLayer(string strLayerName, ref List<OdDbLine> lstOdDbLine)
		{
			try
			{
				List<OdDbEntity> list = new List<OdDbEntity>();
				bool flag = !this.TryGetEntitiesByLayer(strLayerName, EntityType.eLine, ref list);
				if (flag)
				{
					return false;
				}
				lstOdDbLine.AddRange(list.ConvertAll<OdDbLine>((OdDbEntity entity) => entity as OdDbLine));
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		public bool TryGetPolyLinesByLayer(string strLayerName, ref List<OdDbPolyline> lstOdDbPolyline)
		{
			try
			{
				List<OdDbEntity> list = new List<OdDbEntity>();
				bool flag = !this.TryGetEntitiesByLayer(strLayerName, EntityType.ePolyLine, ref list);
				if (flag)
				{
					return false;
				}
				lstOdDbPolyline.AddRange(list.ConvertAll<OdDbPolyline>((OdDbEntity entity) => entity as OdDbPolyline));
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		public bool TryGetBlockRefByLayer(string strLayerName, ref List<OdDbBlockReference> lstOdDbBlockRef)
		{
			try
			{
				List<OdDbEntity> list = new List<OdDbEntity>();
				bool flag = !this.TryGetEntitiesByLayer(strLayerName, EntityType.eBlockRef, ref list);
				if (flag)
				{
					return false;
				}
				lstOdDbBlockRef.AddRange(list.ConvertAll<OdDbBlockReference>((OdDbEntity entity) => entity as OdDbBlockReference));
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		public bool TryGetBlockRefByName(string strBlockName, ref List<OdDbBlockReference> lstOdDbBlockRef, OdGeScale3d refScale = null)
		{
			OdResBuf odResBuf = OdResBuf.newRb(0, "INSERT");
			odResBuf.setNext(OdResBuf.newRb(2, strBlockName));
			OdDbSelectionSet odDbSelectionSet = OdDbSelectionSet.select(this.m_db, odResBuf);
			OdDbObjectIdArray odDbObjectIdArray = odDbSelectionSet.objectIdArray();
			foreach (OdDbObjectId odDbObjectId in odDbObjectIdArray)
			{
				OdDbEntity odDbEntity = (OdDbEntity)odDbObjectId.safeOpenObject(OpenMode.kForRead);
				bool flag = !(odDbEntity is OdDbBlockReference);
				if (!flag)
				{
					OdDbBlockReference odDbBlockReference = odDbEntity as OdDbBlockReference;
					bool flag2 = refScale != null;
					if (flag2)
					{
						OdGeScale3d odGeScale3d = odDbBlockReference.scaleFactors();
						bool flag3 = !Geometry.IsEqual(Math.Abs(odGeScale3d.sx), Math.Abs(refScale.sx), 0.0001) || !Geometry.IsEqual(Math.Abs(odGeScale3d.sy), Math.Abs(refScale.sy), 0.0001);
						if (flag3)
						{
							continue;
						}
					}
					string blockName = this.GetBlockName(odDbBlockReference);
					lstOdDbBlockRef.Add(odDbBlockReference);
				}
			}
			return true;
		}

		public bool TryGetBlockRefByPos(string strLayerName, OdGePoint3d ptPos, ref OdDbBlockReference odDbBlockRef)
		{
			double num = 100000000.0;
			for (double num2 = 500.0; num2 < num / 2.0; num2 *= 2.0)
			{
				OdGePoint3d[] nPoints = new OdGePoint3d[]
				{
					new OdGePoint3d(ptPos.x - num2, ptPos.y - num2, 0.0),
					new OdGePoint3d(ptPos.x - num2, ptPos.y + num2, 0.0),
					new OdGePoint3d(ptPos.x + num2, ptPos.y + num2, 0.0),
					new OdGePoint3d(ptPos.x + num2, ptPos.y - num2, 0.0)
				};
				OdDbSelectionSet odDbSelectionSet = OdDbSelectionSet.select(this.m_db.activeViewportId(), nPoints, OdDbVisualSelection.Mode.kCPoly);
				OdDbObjectIdArray odDbObjectIdArray = odDbSelectionSet.objectIdArray();
				bool flag = false;
				double num3 = double.MaxValue;
				foreach (OdDbObjectId odDbObjectId in odDbObjectIdArray)
				{
					OdDbEntity odDbEntity = (OdDbEntity)odDbObjectId.safeOpenObject(OpenMode.kForRead);
					bool flag2 = !(odDbEntity is OdDbBlockReference);
					if (!flag2)
					{
						OdDbBlockReference odDbBlockReference = odDbEntity as OdDbBlockReference;
						bool flag3 = odDbBlockReference.layer() != strLayerName;
						if (!flag3)
						{
							OdGeExtents3d odGeExtents3d = new OdGeExtents3d();
							bool flag4 = odDbBlockReference.getGeomExtents(odGeExtents3d) > OdResult.eOk;
							if (!flag4)
							{
								OdGePoint3d odGePoint3d = odGeExtents3d.minPoint();
								odGePoint3d.z = 0.0;
								OdGePoint3d odGePoint3d2 = odGeExtents3d.maxPoint();
								odGePoint3d2.z = 0.0;
								OdGePoint3d odGePoint3d3 = odGePoint3d + (odGePoint3d2 - odGePoint3d) / 2.0;
								double num4 = odGePoint3d3.distanceTo(ptPos);
								bool flag5 = num4 < num3;
								if (flag5)
								{
									num3 = num4;
									flag = true;
									odDbBlockRef = odDbBlockReference;
								}
							}
						}
					}
				}
				bool flag6 = flag;
				if (flag6)
				{
					return true;
				}
			}
			return false;
		}

		public string GetBlockName(OdDbBlockReference blkRef)
		{
			OdDbObject odDbObject = blkRef.blockTableRecord().safeOpenObject();
			bool flag = odDbObject == null;
			string result;
			if (flag)
			{
				result = string.Empty;
			}
			else
			{
				OdDbBlockTableRecord odDbBlockTableRecord = odDbObject as OdDbBlockTableRecord;
				result = odDbBlockTableRecord.getName();
			}
			return result;
		}

		public List<OdDbBlockReference> GetBlockRefInRange(List<OdDbBlockReference> lstAllBlockRef, XYZ ptMin, XYZ ptMax, Transform trans)
		{
			List<OdDbBlockReference> list = new List<OdDbBlockReference>();
			foreach (OdDbBlockReference odDbBlockReference in lstAllBlockRef)
			{
				OdGeExtents3d odGeExtents3d = new OdGeExtents3d();
				OdResult geomExtents = odDbBlockReference.getGeomExtents(odGeExtents3d);
				bool flag = geomExtents > OdResult.eOk;
				if (!flag)
				{
					OdGePoint3d odGePoint3d = odGeExtents3d.minPoint();
					OdGePoint3d p = odGeExtents3d.maxPoint();
					OdGePoint3d odGePoint3d2 = odGePoint3d + (p - odGePoint3d) / 2.0;
					XYZ xyz = trans.OfPoint(new XYZ(odGePoint3d2.x, odGePoint3d2.y, 0.0) / 304.8);
					bool flag2 = xyz.X > ptMin.X && xyz.Y > ptMin.Y && xyz.X < ptMax.X && xyz.Y < ptMax.Y;
					if (flag2)
					{
						list.Add(odDbBlockReference);
					}
				}
			}
			return list;
		}

		protected override void Finalize()
		{
			try
			{
				bool flag = this.m_systemServices != null;
				if (flag)
				{
					this.m_systemServices.Dispose();
				}
				bool flag2 = this.m_hostAppServices != null;
				if (flag2)
				{
					this.m_hostAppServices.Dispose();
				}
				TD_Db.odUninitialize();
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
			}
			finally
			{
				base.Finalize();
			}
		}

		private bool TryGetEntitiesByLayer(string strLayerName, EntityType entityType, ref List<OdDbEntity> lstOdDbEntity)
		{
			return this.TryGetEntitiesByType(ref lstOdDbEntity, entityType, strLayerName);
		}

		private bool TryGetEntitiesByType(ref List<OdDbEntity> lstOdDbEntity, EntityType entityType, string strLayerName = "")
		{
			try
			{
				string resVal = string.Empty;
				switch (entityType)
				{
				case EntityType.eLine:
					resVal = "LINE";
					goto IL_66;
				case EntityType.ePolyLine:
					resVal = "LWPOLYLINE";
					goto IL_66;
				case EntityType.eText:
					resVal = "TEXT";
					goto IL_66;
				case EntityType.eMText:
					resVal = "MTEXT";
					goto IL_66;
				case EntityType.eBlockRef:
					resVal = "INSERT";
					goto IL_66;
				}
				return true;
				IL_66:
				OdResBuf odResBuf = OdResBuf.newRb(0, resVal);
				bool flag = strLayerName != "";
				if (flag)
				{
					odResBuf.setNext(OdResBuf.newRb(8, strLayerName));
				}
				OdDbSelectionSet odDbSelectionSet = OdDbSelectionSet.select(this.m_db, odResBuf);
				OdDbObjectIdArray odDbObjectIdArray = odDbSelectionSet.objectIdArray();
				foreach (OdDbObjectId odDbObjectId in odDbObjectIdArray)
				{
					OdDbEntity item = (OdDbEntity)odDbObjectId.safeOpenObject(OpenMode.kForRead);
					lstOdDbEntity.Add(item);
				}
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
				return false;
			}
			return true;
		}

		private ExSystemServices m_systemServices = null;

		private ExHostAppServices m_hostAppServices;

		private OdDbDatabase m_db;
	}
}
